///////////////////////////////////////////////////////////////////////////////////////////////////////
//	Copyright (c) 2010, Blogagic (http://blogagic.com/)
//	All rights reserved.
//
//	Redistribution and use in source and binary forms, with or without modification, 
//	are permitted provided that the following conditions are met:
//
//		- Redistributions of source code must retain the above copyright notice, this list of 
//		  conditions and the following disclaimer.
//		- Redistributions in binary form must reproduce the above copyright notice, this list 
//		  of conditions and the following disclaimer in the documentation and/or other materials 
//		  provided with the distribution.
//
//	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
//	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
//	FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
//	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
//	DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
//	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
//	IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
//	OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
///////////////////////////////////////////////////////////////////////////////////////////////////////

/*
	SparklineBarChart - Sparkline display as a Bar Chart.
	Copyright (C) 2010  Blogagic (http://blogagic.com/)
	Version 1.0

	Licensed under the Creative Commons BSD Licence
	http://creativecommons.org/licenses/BSD/
*/
package com.blogagic.controls
{
	import com.blogagic.controls.sparklineClasses.SparklineChart;
	
	import mx.styles.CSSStyleDeclaration;
	import mx.styles.StyleManager;
	
	/**
	 *  Space between bars.
	 * 
	 *  @default 1
	 */
	[Style(name="barSpacing", type="Number", inherit="no")]
	
	/**
	 *  Color for the bar.
	 * 
	 *  @default 0x828282
	 */
	[Style(name="valueColor", type="Color", format="Color", inherit="no")]
	
	/**
	 *  Bad value color (compared to the threshold).
	 * 
	 *  @default 0xFF0000
	 */
	[Style(name="badColor", type="Color", format="Color", inherit="no")]
	
	/**
	 *  Good value color (compared to the threshold).
	 * 
	 *  @default 0x008000
	 */
	[Style(name="goodColor", type="Color", format="Color", inherit="no")]
	
	/**
	 *  SparklineBarChart displays a Sparkline as a Bar Chart.
	 *  
	 *  <p><code>SparklineBarChart</code> implements <code>IListItemRenderer</code>
	 *  and <code>IDropInListItemRenderer</code> allowing to use <code>SparklineBarChart</code>
	 *  as an item renderer inside a data grid or list control.  
	 *  <code>SparklineBarChart</code> can also be used as a regular standalone control.</p>
	 * 
	 *  @mxml
	 *
	 *  <p>The SparklineBarChart class inherits all the properties and styles of its parent 
	 *  classes and adds the following styles:</p>
	 *
	 *  <pre>
	 *  &lt;mx:SparklineBarChart
	 *    <b>Styles</b>
	 *    barSpacing="1"
	 *    valueColor="0x828282"
	 *    badColor="0xFF0000"
	 *    goodColor="0x008000"
	 *  /&gt;
	 *  </pre>
	 *
	 *  @author JYC
	 */	
	public class SparklineBarChart extends SparklineChart
	{
		//--------------------------------------------------------------------------
		//
		//  Constructor
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  Constructor
		 */
		public function SparklineBarChart()
		{
			super();
		}	
		
		//--------------------------------------------------------------------------
		//
		//  Styles
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  @private
		 */
		private static var classConstructed:Boolean = classConstruct();
		
		/**
		 *  @private
		 *  Styles initialization.
		 */
		private static function classConstruct():Boolean {
			
			var style:CSSStyleDeclaration = StyleManager.getStyleDeclaration("SparklineBarChart");
			if (!style) {
				style = new CSSStyleDeclaration();
				
				style.defaultFactory = function():void {
					this.barSpacing = 1;
					this.valueColor = 0x828282;
					this.goodColor = 0x008000;
					this.badColor = 0xFF0000;
				};
				StyleManager.setStyleDeclaration("SparklineBarChart", style, true);
			}
			else {
				if (style.getStyle("barSpacing") == undefined) {
					style.setStyle("barSpacing", "1");	        		
				}
				if (style.getStyle("valueColor") == undefined) {
					style.setStyle("valueColor", "0x828282");	        		
				}
				if (style.getStyle("goodColor") == undefined) {
					style.setStyle("goodColor", "0x008000");	        		
				}
				if (style.getStyle("badColor") == undefined) {
					style.setStyle("badColor", "0xFF0000");	        		
				}
			}
			
			return true;        
		}
		
		/**
		 *  @private
		 */
		override public function styleChanged(styleProp:String):void {
			super.styleChanged(styleProp);
			
			switch (styleProp) {
				case "barSpacing":
				case "valueColor":
				case "goodColor":
				case "badColor":
					invalidateDisplayList();
					break;
			}
		}
		
		//--------------------------------------------------------------------------
		//
		//  Methods
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  Update scaling factor used to convert data values and pixels on the x-axis.
		 * 
		 *  @param unscaledWidth Width to be used to compute the horizontal scaling factor.
		 */
		override protected function updateHorizontalScale(unscaledWidth:Number):void {
			if (!dataProvider)
				return;
			
			if (_horizontalScaleDirty) {
				var range:Number = xMax - xMin;
				range = range + range/nbItems;	// Add enough space for the last bar
				
				var w:Number = unscaledWidth - 2 * getPadding();
				if (range != 0)
					_horizontalScale = w / range;
				else
					_horizontalScale = w;
				
				_horizontalScaleDirty = false;
			}
		}
		
		/**
		 *  Draws the Sparkline as a Bar Chart.
		 * 
		 *  @param chartWidth Width of the chart area.
		 *  @param chartHeight Height of the chart area.
		 */
		override protected function drawChart(chartWidth:Number, chartHeight:Number):void
		{
			var i:uint = 0;
			var l:uint = dataProvider.length;
			var skip:uint = Math.max(0, l-maxPlots);
			
			// Computes width of each bar
			var barWidth:Number = chartWidth / nbItems;
			var renderedWidth:Number = barWidth - getStyle("barSpacing");
			
			var padding:Number = getPadding();
			
			var color:Number;
			var aboveColor:Number;
			var belowColor:Number;
			var threshPos:Number;
			
			// Define possible bar colors depending on threshold visibility 
			if (showThreshold) {
				if (upperIsFault) {
					aboveColor = getStyle("badColor");
					belowColor = getStyle("goodColor");
				}
				else {
					aboveColor = getStyle("goodColor");
					belowColor = getStyle("badColor");
				}
				threshPos = getYPosition(threshold, chartHeight, padding);
			}
			else
				color = getStyle("valueColor");
			
			for (i = skip; i < l; i++)
			{
				computePosition(i, skip, chartWidth, chartHeight, padding);
				
				// Take care of missing values (when xField or yField != "")
				if (!isNaN(position.x) && !isNaN(position.y)) {
					graphics.lineStyle();
					
					if (showThreshold) {
						// If threshold is visible, select bar color by comparing data point value with threshold
						if (position.y <= threshPos) {
							graphics.beginFill(aboveColor);
						}
						else {
							graphics.beginFill(belowColor);
						}
						// Draw the bar above or below the threshold line
						graphics.drawRect(position.x, threshPos, renderedWidth, position.y-threshPos);
					}
					else {
						graphics.beginFill(color);
						graphics.drawRect(position.x, position.y, renderedWidth, chartHeight-position.y-padding);
					}
				}
				graphics.endFill();
			}
		}
	}
}
